import type { SFCParseResult } from '@vue/compiler-sfc';

import { compileScript } from '@vue/compiler-sfc';
import { parse } from '@vue/compiler-sfc';

const formatOptions = (result: any, options: any = {}): string => {
  if (result && result.attrs && result.attrs.addGlobalClass) {
    options.addGlobalClass = result.attrs.addGlobalClass;
  }
  if (result && result.attrs && result.attrs.styleIsolation) {
    options.styleIsolation = result.attrs.styleIsolation;
  }
  if (result && result.attrs && result.attrs.multipleSlots) {
    options.multipleSlots = result.attrs.multipleSlots;
  }
  if (result && result.attrs && result.attrs.virtualHost) {
    options.virtualHost = result.attrs.virtualHost;
  }

  return JSON.stringify(options);
}

export const supportScriptName = (code: string, id: string, { descriptor }: SFCParseResult): string => {
  if (!descriptor.script && descriptor.scriptSetup && !descriptor.scriptSetup.attrs?.extendIgnore) {
    const result = compileScript(descriptor, { id });
    const lang = result.attrs.lang;
    const answer = [code];

    answer.push(`<script ${lang ? `lang="${lang}"` : ''}>\r\n`);
    answer.push(`import { defineComponent } from 'vue';\r\n`);
    answer.push(`export default defineComponent({`);

    // 处理inheritAttrs属性
    if (result && result.attrs && result.attrs.inheritAttrs) {
      answer.push(`inheritAttrs:${result.attrs.inheritAttrs},\r\n`);
    }

    // 处理组件名称属性
    if (result && result.attrs && result.attrs.name) {
      answer.push(`name:'${result.attrs.name}',\r\n`);
    }

    // 处理额外的配置信息(https://uniapp.dcloud.net.cn/tutorial/vue-api.html#%E5%85%B6%E4%BB%96%E9%85%8D%E7%BD%AE)
    const options = formatOptions(result);
    if (options && options !== '{}') {
      answer.push(`options:${options},\r\n`);
    }

    answer.push(`})\r\n`);
    answer.push(`</script>\r\n`);

    if (code && answer.length > 6) {
      return answer.join('');
    }
  }

  return code;
}

/**
 * 代码处理函数
 */
export const transform = (code: string, id: string): string => {
  if (/\.vue$/.test(id) || /\.vue\?.*type=script.*/.test(id)) {
    return supportScriptName(code, id, parse(code));
  }

  return code;
}